package co.edu.usbcali.raju.model;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.log4j.Logger;

import co.edu.usbcali.raju.games.chess.engine.ChessRuleEngine;
import co.edu.usbcali.raju.games.chess.helpers.PlBoardWrapper;
import co.edu.usbcali.raju.games.chess.model.ChessBoard;
import co.edu.usbcali.raju.games.chess.model.ChessCell;

public abstract class MoveChooser {
	
	private Map<IEvaluator, Float> evaluators=new HashMap<IEvaluator, Float>();
	protected float[] evaluations;
	protected float totalEvaluation;
	private static Logger logger=Logger.getLogger(MoveChooser.class.getName());
	protected float minEvaluation=999999999999f;
	protected int minMove=-1;
	protected float maxEvaluation=-999999999999f;
	protected int maxMove=-1;
	
	public abstract Move chooseMove(Board board,List<Move> moves);
	
	public void putEvaluator(IEvaluator evaluator,float weight){
		evaluators.put(evaluator, weight);
	}
	public void removeEvaluator(IEvaluator evaluator){
		evaluators.remove(evaluator);
	}
	
	public float evaluate(Board board,List<Move> moves,int deep){
		ChessRuleEngine ruleEngine=ChessRuleEngine.getInstance(); 
		evaluations=new float[moves.size()];
		totalEvaluation=0;
		int i=0;
		for (Move move : moves) {
			logger.debug("Evaluando la jugada "+move.toString());
			ChessBoard test=new ChessBoard((ChessBoard)board);
			Move testMove=clonMove(move, test);
			test=(ChessBoard)ruleEngine.transition(test, testMove);
			logger.debug("Evaluando el tablero "+test);
			Set<IEvaluator> set=evaluators.keySet();
			float moveEval=0;
			for (IEvaluator iEvaluator : set) {
				float eval=iEvaluator.evaluate(test,player)*evaluators.get(iEvaluator);
				moveEval+=eval;
			}
			moveEval=complementaryEval(test,testMove,moveEval,deep);
/**			if(deep>1){
				List<Move> ms=PlBoardWrapper.getInstance().getMoves(test);
			}
*/			evaluations[i]=moveEval;
			if(moveEval<minEvaluation){
				minEvaluation=moveEval;
				minMove=i;
			}
			if(moveEval>maxEvaluation){
				maxEvaluation=moveEval;
				maxMove=i;
			}
			totalEvaluation+=moveEval;
			i++;
		}
		return totalEvaluation;
	}
	
	/**
	 * Update Move fixing cells to correct board
	 * @return
	 */
	public Move clonMove(Move move,Board board){
		ChessBoard cBoard=(ChessBoard)board;
		Move newMove=new Move(); 
		List<Step> steps=move.getSteps();
		for (Step step : steps) {
			Step newStep=new Step();
			ChessCell cell=(ChessCell)step.getTarget();
			newStep.setTarget(cBoard.getCells().get(cell.getAbsolutePosition()));
			ChessCell source=(ChessCell)step.getPiece().getCell();
			//ChessPiece piece=(ChessPiece)source.getPieces().get(0);
			newStep.setPiece(cBoard.getCells().get(source.getAbsolutePosition()).getPieces().get(0));
			newMove.addStep(newStep);
		}
		return newMove;
	}
	
	public abstract float complementaryEval(ChessBoard board,Move move,float eval,int deep);

}
